#include"client.h"
#include "my_header.h"
#include <unistd.h>

void* thread_puts(void* arg){
    threadMsg_t *threadMsg = (threadMsg_t*)arg;

    // 子线程建立新的tcp连接
    int sockfd = socket(AF_INET,SOCK_STREAM,0);
    struct sockaddr_in addr;
    addr.sin_addr.s_addr = inet_addr(threadMsg->ip);
    addr.sin_port = htons(atoi(threadMsg->port));
    int ret = connect(sockfd,(struct sockaddr*)&addr,sizeof(addr));
    ERROR_CHECK(ret,-1,"connect");
    
    // 先发送命令给主线程
    send(sockfd,&threadMsg->train,sizeof(threadMsg->train.type) + sizeof(threadMsg->train.length) + threadMsg->train.length,0);

    // 与工人的业务逻辑
    char sha1[41] = {0};
    char buf[256];
    char *filename = strrchr(threadMsg->path,'/');
    filename++;

    sha1_file(filename,sha1);
    // 先发送文件名
    sendMsg(sockfd,filename);
    recvMsg(sockfd,buf);
    // 收到1发哈希值，0不发哈希值
    if(strcmp(buf,"1") == 0){
        // 要发哈希值
        sendMsg(sockfd,sha1);
        bzero(&buf,sizeof(buf));
        recvMsg(sockfd,buf);
        // 收到1发文件，0不发文件
        if(strcmp(buf,"1") == 0){
            sendFile(sockfd,filename);
            printf("上传成功\n");
        }
        else{
            printf("秒传成功\n");
        }
    }
    else{
        printf("路径错误\n");
    }

    close(sockfd);
    return NULL;
}

void* thread_gets(void* arg){
    threadMsg_t *threadMsg = (threadMsg_t*)arg;

    // 子线程建立新的tcp连接
    int sockfd = socket(AF_INET,SOCK_STREAM,0);
    struct sockaddr_in addr;
    addr.sin_addr.s_addr = inet_addr(threadMsg->ip);
    addr.sin_port = htons(atoi(threadMsg->port));
    int ret = connect(sockfd,(struct sockaddr*)&addr,sizeof(addr));
    ERROR_CHECK(ret,-1,"connect");

    // 先发送命令给主线程
    send(sockfd,&threadMsg->train,sizeof(threadMsg->train.type) + sizeof(threadMsg->train.length) + threadMsg->train.length,0);

    // 与工人的业务逻辑
    // 先接收信息，1就接收文件，0就代表没有这个文件
    char buf[256];
    recvMsg(sockfd,buf);
    if(strcmp(buf,"1") == 0){
        recvFile(sockfd);
        printf("下载文件成功\n");
    }
    else{
        printf("该文件不存在\n");
    }

    close(sockfd);
    return NULL;
}

int main(int argc, char *argv[]){
    //第一步先根据ip和端口号与服务端建立连接
    ARGS_CHECK(argc,3);
    int sockfd=socket(AF_INET,SOCK_STREAM,0);
    struct sockaddr_in addr;
    addr.sin_family=AF_INET;
    addr.sin_port=htons(atoi(argv[2]));
    addr.sin_addr.s_addr=inet_addr(argv[1]);
    int ret=connect(sockfd,(struct sockaddr*)&addr,sizeof(addr));
    ERROR_CHECK(ret,-1,"connect");
    printf("Connected to the server successfully.\n");


    int epfd=epoll_create(1);
    struct epoll_event event;
    event.events=EPOLLIN;
    event.data.fd=sockfd;
    epoll_ctl(epfd,EPOLL_CTL_ADD,sockfd,&event);

    event.data.fd=STDIN_FILENO;
    epoll_ctl(epfd,EPOLL_CTL_ADD,STDIN_FILENO,&event);
    //将sockfd和stdin加入监听

    char buf[512]={0};
    char username[50]={0};
    char password[50]={0};
    struct epoll_event events[10];
    // 判断是登陆还是注册
    int flag_log;
    /*-----------------登录，注册逻辑--------------------*/
    while(1){
        fflush(stdin);
        flag_log = 0;
        printf("\033[1;37mPlease enter 1 to register a new user;");
        printf("or enter 2 to login: \033[0m");
        fflush(stdout);

        char buf[10] = {0};
        read(STDIN_FILENO, buf, sizeof(buf));
        flag_log = atoi(buf);

        if(flag_log == 1){
            // 注册
            int ret = uRegister(sockfd,password);
            if(ret == -1){
                printf("注册失败\n");
                continue;
            }
            else if(ret == 2){
                printf("用户已存在，注册失败\n");
                continue;
            }
            else{
                printf("注册成功\n");
                continue;
            }

        }
        else if(flag_log == 2){
            // 登录
            int ret = uLogin(sockfd,username,password);
            if(ret == 2){
                printf("用户未注册\n");
                continue;
            }
            else{
                printf("登录成功！你真是个天才啊\n");
                break;
            }
        }
        else{
            // 非法指令
            printf("Wrong number!\n");
            continue;
        }

    }


    /*---------------------业务逻辑-----------------------*/
    int flag=-1;// 指令标识
    char token[41] = {0};
    recvn(sockfd,token,40);
    DEBUG_PRINT("token = %s\n",token);
    train_t train;
    char cmd[256] = {0};
    threadMsg_t threadMsg;
    while(1)
    {
        int num=epoll_wait(epfd,events,10,-1);
        for(int i=0;i<num;i++){
            if(events[i].data.fd==STDIN_FILENO){
                bzero(buf,sizeof(buf));
                bzero(cmd,sizeof(cmd));
                read(STDIN_FILENO,buf,sizeof(buf));
                bzero(&train,sizeof(train));
                
                //对命令进行分析看是否符合格式
                flag=formVertify(buf);
                DEBUG_PRINT("命令解析结束\n");
                if(flag == -1){
                    printf("Please re-enter due to formatting error.\n");//格式错误
                    continue;
                }
                else if(flag == PUTS){
                    // 发文件
                    bzero(&threadMsg,sizeof(threadMsg));
                    threadMsg.train.type = PUTS;
                    size_t max_len = strlen(username)+strlen(password)+strlen(token)+strlen(buf)+3+1;
                    char len[max_len];
                    snprintf(cmd,sizeof(len),"%s!%s!%s!%s",username,password,token,buf);
                    DEBUG_PRINT("cmd = %s\n",cmd);
                    threadMsg.train.length = strlen(cmd);
                    strcpy(threadMsg.train.data,cmd);

                    // 创建子线程
                    pthread_t thread;
                    
                    threadMsg.fd = sockfd;
                    char filename[50] = {0};
                    sscanf(buf,"%*s %s",filename);
                    strcpy(threadMsg.path,filename);
                    strcpy(threadMsg.ip,argv[1]);
                    strcpy(threadMsg.port,argv[2]);

                    if(pthread_create(&thread,NULL,thread_puts,&threadMsg) != 0){
                        perror("创建线程失败\n");
                        return 1;
                    }

                    // 等待子线程完成
                    pthread_join(thread,NULL);


                }
                else if(flag == GETS){
                    // 下载文件        
                    bzero(&threadMsg,sizeof(threadMsg));
                    threadMsg.train.type = GETS;
                    size_t max_len = strlen(username)+strlen(password)+strlen(token)+strlen(buf)+3+1;
                    char len[max_len];
                    snprintf(cmd,sizeof(len),"%s!%s!%s!%s",username,password,token,buf);
                    DEBUG_PRINT("cmd = %s\n",cmd);
                    threadMsg.train.length = strlen(cmd);
                    strcpy(threadMsg.train.data,cmd);

                    // 创建子线程
                    pthread_t thread;
                    threadMsg.fd = sockfd;
                    char filename[50] = {0};
                    sscanf(buf,"%*s %s",filename);
                    strcpy(threadMsg.path,filename);
                    strcpy(threadMsg.ip,argv[1]);
                    strcpy(threadMsg.port,argv[2]);

                    if(pthread_create(&thread,NULL,thread_gets,&threadMsg) != 0){
                        perror("创建线程失败\n");
                        return 1;
                    }

                    // 等待子线程完成
                    pthread_join(thread,NULL);


                }
                else if(flag == LS){
                    // LS
                    train.type = LS;
                    size_t max_len = strlen(username)+strlen(password)+strlen(token)+strlen(buf)+3+1;
                    char len[max_len];
                    snprintf(cmd,sizeof(len),"%s!%s!%s!%s",username,password,token,buf);
                    DEBUG_PRINT("cmd = %s\n",cmd);
                    train.length = strlen(cmd);
                    strcpy(train.data,cmd);
                    send(sockfd,&train,sizeof(train.type) + sizeof(train.length) + train.length,0);

                    char result[256] = {0};
                    recvMsg(sockfd,result);
                    printf("%s\n",result);
                }
                else if(flag == CD){
                    // CD
                    train.type = CD;
                    size_t max_len = strlen(username)+strlen(password)+strlen(token)+strlen(buf)+3+1;
                    char len[max_len];
                    snprintf(cmd,sizeof(len),"%s!%s!%s!%s",username,password,token,buf);
                    DEBUG_PRINT("cmd = %s\n",cmd);
                    train.length = strlen(cmd);
                    strcpy(train.data,cmd);
                    send(sockfd,&train,sizeof(train.type) + sizeof(train.length) + train.length,0);

                    char result[256] = {0};
                    recvMsg(sockfd,result);
                    printf("%s\n",result);

                }
                else if(flag == MKDIR){
                    // MKDIR
                    train.type = MKDIR;
                    size_t max_len = strlen(username)+strlen(password)+strlen(token)+strlen(buf)+3+1;
                    char len[max_len];
                    snprintf(cmd,sizeof(len),"%s!%s!%s!%s",username,password,token,buf);
                    DEBUG_PRINT("cmd = %s\n",cmd);
                    train.length = strlen(cmd);
                    strcpy(train.data,cmd);
                    send(sockfd,&train,sizeof(train.type) + sizeof(train.length) + train.length,0);

                    char result[256] = {0};
                    recvMsg(sockfd,result);
                    printf("%s\n",result);
                    
                }
                else if(flag == RMDIR){
                    train.type = RMDIR;
                    size_t max_len = strlen(username)+strlen(password)+strlen(token)+strlen(buf)+3+1;
                    char len[max_len];
                    snprintf(cmd,sizeof(len),"%s!%s!%s!%s",username,password,token,buf);
                    DEBUG_PRINT("cmd = %s\n",cmd);
                    train.length = strlen(cmd);
                    strcpy(train.data,cmd);
                    send(sockfd,&train,sizeof(train.type) + sizeof(train.length) + train.length,0);

                    char result[256] = {0};
                    recvMsg(sockfd,result);
                    printf("%s\n",result);

                }
                else if(flag == REMOVE){
                    train.type = REMOVE;
                    size_t max_len = strlen(username)+strlen(password)+strlen(token)+strlen(buf)+3+1;
                    char len[max_len];
                    snprintf(cmd,sizeof(len),"%s!%s!%s!%s",username,password,token,buf);
                    DEBUG_PRINT("cmd = %s\n",cmd);
                    train.length = strlen(cmd);
                    strcpy(train.data,cmd);
                    send(sockfd,&train,sizeof(train.type) + sizeof(train.length) + train.length,0);

                    char result[256] = {0};
                    recvMsg(sockfd,result);
                    printf("%s\n",result);

                }
                else if(flag == PWD){
                    train.type = PWD;
                    size_t max_len = strlen(username)+strlen(password)+strlen(token)+strlen(buf)+3+1;
                    char len[max_len];
                    snprintf(cmd,sizeof(len),"%s!%s!%s!%s",username,password,token,buf);
                    DEBUG_PRINT("cmd = %s\n",cmd);
                    train.length = strlen(cmd);
                    strcpy(train.data,cmd);
                    send(sockfd,&train,sizeof(train.type) + sizeof(train.length) + train.length,0);

                    char result[256] = {0};
                    recvMsg(sockfd,result);
                    printf("%s\n",result);

                }
            }
            else if(events[i].data.fd == sockfd){
                // 收到来自服务端的信息
            }
            else{

            }
        }
    }
}

